home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
system
/
csh4.zip
/
MAIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1985-09-05
|
12KB
|
516 lines
#include <debug.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <fcntl.h>
#include <setjmp.h>
typedef struct /* used to find builtin commands */
{
char *cmdname;
int (*func)();
} builtin;
extern builtin commands[];
extern char histerr[];
extern int j,hiscount;
extern char *history[];
extern int histsize;
extern int numcmds;
char *version = "SHELL VERSION 1.1 Kent Williams";
jmp_buf env;
char *pipename[] =
{
"\\shtmp1",
"\\shtmp2"
};
char cmdbuf[512];
int currname = 0;
int result = 0;
main(argc,argv)
char *argv[];
{
register int i;
int repeat, quiet, state, inpipe = 0;
static char localbuf[256];
static char histbuf[256];
static char tail[256];
int histindex,argindex,takeline;
char *local = localbuf;
register char *current,*curr_save;
char *ntharg(), *argptr;
char *savestr();
signal(SIGINT,SIG_IGN); /* ignore breaks */
quiet = !isatty(0); /* quiet = batch shell */
/* initialize local environment */
init_env();
/* command interpreter loop */
for(j=0;;)
{
/* kill tmp files */
unlink(pipename[0]); unlink(pipename[1]);
hiscount = j % histsize; /* hiscount is current position in history */
if(!quiet)
fprintf(stderr,"%d%% ",j);
/*
* The following code simply reads a line from standard input.
* It is so complicated because when you save the standard stream
* files and execute another program/command, standard input is
* left in an uncertain state - the FILE stdin seems to be at EOF,
* even when standard input is associated with the console, and
* cr/lf combinations show up as line terminators, whereas usually
* only linefeeds get placed in the input stream.
* WHY? beats me. Something could be wrong with
* 1. AZTEC C runtime
* 2. PCDOS
* 3. Me
* 4. All three, or permutations of 1-3 reducto ad absurdum.
* All I know is this works
*/
/* clear command buffer so string read is null terminated */
setmem(cmdbuf,sizeof(cmdbuf),0);
for (current = cmdbuf;;current++)
{
int readresult;
if ((readresult = read(0,current,1)) == 0 ||
readresult == -1)
{
exit (0);
}
if (*current == '\r')
{
if ((readresult = read(0,current,1)) == 0 ||
readresult == -1)
{
exit (0);
}
*current = '\0';
break;
}
else if (*current == '\n')
{
*current = '\0'; /* terminate string */
break;
}
}
current = cmdbuf; /* point current at start of buffer */
/*
* end of input weirdness
*/
/* if we're recycling history strings, free previous one */
if (history[hiscount])
free(history[hiscount]);
/* save current in history array */
history[hiscount] = savestr(current);
#define CHAR -1
#define PIPE -2
#define DOUBLEQUOTES -3
#define SINGLEQUOTES -4
#define EMIT -5
#define COMPOUND -6
#define DONE -7
#define EATWHITESPACE -8
#define HISTORY -9
#define CONTINUE -0xA
/* parse command for compound statements and pipes */
state = EATWHITESPACE;
local = localbuf;
setmem(localbuf,sizeof(localbuf),0); /* clear buffer */
while (state != DONE && state != CONTINUE)
{
switch(state)
{
case CHAR:
switch(*current)
{
case '\0':
*local = '\0';
state = EMIT;
break;
case '"' :
state = DOUBLEQUOTES;
*local++ = *current;
break;
case '/' :
*local++ = '\\';
break;
case '\'':
state = SINGLEQUOTES;
*local++ = *current;
break;
case '\\':
*local++ = *++current;
break;
case ';':
*local = '\0';
state = COMPOUND;
break;
case '|':
*local = '\0';
state = PIPE;
break;
case '!':
state = HISTORY;
break;
default:
*local++ = *current;
break;
}
current++;
break;
case EMIT:
if (inpipe)
{
inpipe = 0;
strcat(localbuf," < ");
strcat(localbuf,pipename[currname]);
}
command(localbuf);
state = DONE;
break;
case COMPOUND:
if (inpipe)
{
inpipe = 0;
strcat(localbuf," < ");
strcat(localbuf,pipename[currname]);
}
command(localbuf);
local = localbuf;
setmem(localbuf,sizeof(localbuf),0); /* clear buffer */
state = EATWHITESPACE;
break;
case SINGLEQUOTES:
switch (*current)
{
case '\0':
write(2,"No closing quotes!!\r\n",21);
state = DONE;
break;
case '\'':
state = CHAR;
*local++ = *current;
break;
#ifdef TEST
case '\\':
*local++ = *++current;
break;
#endif
default:
*local++ = *current;
}
current++;
break;
case DOUBLEQUOTES:
switch(*current)
{
case '\0':
write(2,"No closing quotes!!\r\n",21);
state = DONE;
break;
case '"':
state = CHAR;
break;
#ifdef TEST
case '\\':
++current;
break;
#endif
}
*local++ = *current++;
break;
case HISTORY:
/* handle history substitutions */
setmem(histbuf,sizeof(histbuf),0); /* clear buffer */
/* save current pointer into command buffer */
curr_save = current;
DEBUGGER(fprintf(stderr,"current = %s\n",current););
/* copy command head */
strncpy(histbuf,cmdbuf,(int)(current-cmdbuf)-1);
/* takeline means take all arguments past current one */
takeline = 0;
/* parse history expression */
switch (*current)
{
case '!': /* last command line */
DEBUGGER(fprintf(stderr,"last command\n"););
if (j) /* special case first time through */
{
histindex = hiscount ? hiscount - 1 : histsize - 1;
}
else
{
/* force error condition */
write(2,histerr,strlen(histerr));
state = CONTINUE;
}
current++; /* point to next */
break;
case '-': /* negative (relative #) */
/* a particular numbered command */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
DEBUGGER(fprintf(stderr,\
"numbered command current = %s\n",current););
/* repeat numbered command */
repeat = atoi(current);
if (repeat < 0) /* handle relative addressing */
repeat += j;
/* if command is within range */
if ((j - repeat) <= histsize && repeat < j)
{
histindex = repeat % histsize;
}
else
{
state = CONTINUE;
}
DEBUGGER(fprintf(stderr,"number %d\n",histindex););
while(isdigit(*current)||*current=='-')
++current;
break;
default:
write(2,"Bad history expression\r\n",24);
state = CONTINUE;
break;
}
if (state == CONTINUE) /* error state */
break;
/* look for particular argument substitutions */
DEBUGGER(fprintf(stderr,\
"looking for colon expression, current = %s\n",current););
switch (*current)
{
/* we want the whole enchilada */
case '\0':
case '\t':
case '\r':
case '\n':
case ' ':
DEBUGGER(fprintf(stderr,"whole cmdline\n"););
DEBUGGER(fprintf(stderr,"current = %s\n",current););
strcat(histbuf,history[histindex]);
state = CHAR;
break;
case ':':
++current; /* point past colon */
DEBUGGER(fprintf(stderr,"current = %s\n",current););
switch (*current)
{
case '^':
argindex = 1;
++current;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
/* index of argument */
argindex = atoi(current);
DEBUGGER(fprintf(stderr,"%s = %d\n",current,argindex););
while(isdigit(*current))
++current;
if (*current = '*')
{
takeline = 1;
current++;
}
break;
case '$':
argindex = lastarg(history[histindex]);
current++;
break;
case '*':
takeline = 1; /* take arg 1 t